package com.gmall.data.service;

import com.gmall.data.api.UserActionCountQueryService;
import com.gmall.data.pojo.RuleAtomicParam;
import com.gmall.data.pojo.RuleParam;
import com.gmall.data.utils.ConnectionUtil;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;

/**
 * clickhouse用户行为次数核心查询服务
 */
@Slf4j
public class UserActionCountQueryServiceChImpl implements UserActionCountQueryService {

    private Connection conn;

    public UserActionCountQueryServiceChImpl() {
        conn = ConnectionUtil.getChConnection();
    }

    /**
     * 根据给定的deviceId，查询这个人是否满足ruleParam中的所有“次数类"规则条件
     *
     * @param deviceId  要查询的用户
     * @param ruleParam 规则参数对象
     * @return 条件查询的结果是否成立
     */
    @Override
    public boolean queryActionCounts(String deviceId, RuleParam ruleParam) {
        // 获取规则中的次数条件规则列表
        List<RuleAtomicParam> params = ruleParam.getUserActionCountParams();

        // 对次数条件规则列表进行遍历，查询每一个原子条件是否都满足
        for (RuleAtomicParam param : params) {
            queryActionCounts(deviceId, param, ruleParam.getRuleId());
        }

        // 如果走到这一句代码，说明上面的每一个原子条件查询后都满足规则，那么返回最终结果true
        return true;
    }

    /**
     * 查询单个行为count条件是否成立
     *
     * @param deviceId    设备id
     * @param atomicParam 原子条件
     * @param ruleId      是否成立
     * @return
     */
    @Override
    public boolean queryActionCounts(String deviceId, RuleAtomicParam atomicParam, String ruleId) {
        // 对当前的原子条件拼接查询sql
        String sql = atomicParam.getCountQuerySql();

        try {
            // 获取一个clickhouse的jdbc连接
            PreparedStatement ps = conn.prepareStatement(sql);

            // 需要将sql中的deviceId占位符替换成真实deviceId
            // TODO 当前把rangeStart和rangeEnd
            ps.setString(1, deviceId);
//            ps.setLong(2, atomicParam.getRangeStart());
//            ps.setLong(3, atomicParam.getRangeEnd());

            ResultSet resultSet = ps.executeQuery();

            // resultSet只有一行，所以while只循环一次
            while (resultSet.next()) {
                int realCnt = (int) resultSet.getLong(2);

                // 将查询结果返回给规则参数对象的次数(阈值)
                atomicParam.setRealCnt(realCnt);
            }

            // 在遍历查询的过程中，只要有一个原子条件查询结果不满足，则直接返回最终结果false
            if (atomicParam.getRealCnt() < atomicParam.getCnt())
                return false;
            else
                return true;
        } catch (Exception e) {
            log.error("failed to ChImpl.queryActionCounts,querySql={},error={}", sql, e);
            return false;
        }
    }
}
